package com.itheima.tanhua.interceptor;

import com.itheima.tanhua.domain.User;
import com.itheima.tanhua.exception.BusinessException;
import com.itheima.tanhua.utils.JwtUtils;
import com.itheima.tanhua.utils.UserHolder;
import com.itheima.tanhua.vo.ErrorResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.time.Duration;

/**
 * @author Lff
 * @date 2022/3/24
 * 请求拦截 验证用户是否登录
 */
@Slf4j
public class TokenInterceptor implements HandlerInterceptor {
    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 权限校验
     * 处理数据
     *
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //获取token
        String token = request.getHeader("Authorization");
        //检验token
        //非法token
        if (!JwtUtils.verifyToken(token)) {
            //抛出异常 用户未登录
            //打印请求地址
            log.info("本次请求Url ==> {},\n被拦截" + request.getRequestURI());
            throw new BusinessException(ErrorResult.notLoginError());
        }
        //token失效
       /* String result = checkTokenExpired(token);
        //如果result不为null说明token过期了，需要重新获取token
//        token = result == null ? token : result;
        if (result == null) {
            //说明token合法有效，啥也不做
        } else if (result.startsWith("Expired")) { //token已过期
            //更新之后的token
            token = result.split("-")[1];
        } else if (result != null) {
            //缓存中的新的token
            token = result;
        }*/
        //获取token中的id并存储
        String idStr = JwtUtils.getClaims(token).get("id").toString();
        Long id = Long.valueOf(idStr);
        String phone = (String) JwtUtils.getClaims(token).get("phone");
        User user = new User();
        user.setId(id.longValue());
        user.setMobile(phone);
        UserHolder.setUser(user);
        //放行
        return true;
    }

    /**
     * 资源释放
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        //清除线程池中的ThreaLoad数据，防止内存溢出
        UserHolder.remove();
    }

    /**
     * 如果token过期或者失效，就返回一个新的token
     * 新的token从缓存中获取
     * 否则返回null
     *
     * @param oldToken
     * @return
     */
    public String checkTokenExpired(String oldToken) {
        //是否是过期的token
        boolean isExpired = false;
        //获取缓存中的旧token
        String cacheToken = (String) redisTemplate.opsForValue().get("token");
        String newToken = (String) redisTemplate.opsForValue().get("newToken");
        //用户传过来的token没有在缓存中失效，并且新的token没有生成
        if (newToken == null || newToken.equals("")) {
            if (oldToken.equals(cacheToken)) {
                //一切正常
                return null;
            }
            //token过期
            return "Expired-" + cacheToken;
        }

        //替换缓存中的token为新token  60分钟
        redisTemplate.opsForValue().set("token", newToken, Duration.ofMinutes(90));
        //删除newToken
        redisTemplate.delete("newToken");
        //代表以及过期
        return newToken;
    }
}
